using EOSDigital.SDK;
using System;
using System.IO;

namespace EOSDigital.API
{
	public class SDKStream : Stream
	{
		private IntPtr _Reference;

		public override bool CanRead
		{
			get
			{
				return true;
			}
		}

		public override bool CanSeek
		{
			get
			{
				return true;
			}
		}

		public override bool CanWrite
		{
			get
			{
				return true;
			}
		}

		public override long Length
		{
			get
			{
				if (CanonSDK.IsVerGE34)
				{
					long result = default(long);
					CanonSDK.EdsGetLength(this.Reference, out result);
					return result;
				}
				int num = default(int);
				CanonSDK.EdsGetLength(this.Reference, out num);
				return num;
			}
		}

		public override long Position
		{
			get
			{
				if (CanonSDK.IsVerGE34)
				{
					long result = default(long);
					CanonSDK.EdsGetPosition(this.Reference, out result);
					return result;
				}
				int num = default(int);
				CanonSDK.EdsGetPosition(this.Reference, out num);
				return num;
			}
			set
			{
				this.Seek(value, System.IO.SeekOrigin.Begin);
			}
		}

		public IntPtr Reference
		{
			get
			{
				return this._Reference;
			}
			protected set
			{
				this._Reference = value;
			}
		}

		public SDKStream(IntPtr sdkStream)
		{
			if (sdkStream == IntPtr.Zero)
			{
				throw new ArgumentNullException("sdkStream");
			}
			this.Reference = sdkStream;
		}

		public SDKStream(string filepath, FileCreateDisposition createDisposition, EOSDigital.SDK.FileAccess access)
		{
			if (filepath == null)
			{
				throw new ArgumentNullException("filepath");
			}
			ErrorHandler.CheckError(CanonSDK.EdsCreateFileStreamEx(filepath, createDisposition, access, out this._Reference));
		}

		public SDKStream(long length)
		{
			ErrorCode errorCode = (!CanonSDK.IsVerGE34) ? CanonSDK.EdsCreateMemoryStream((int)length, out this._Reference) : CanonSDK.EdsCreateMemoryStream(length, out this._Reference);
			ErrorHandler.CheckError(errorCode);
		}

		public SDKStream(byte[] buffer)
		{
			if (buffer == null)
			{
				throw new ArgumentNullException("buffer");
			}
			ErrorCode errorCode = (!CanonSDK.IsVerGE34) ? CanonSDK.EdsCreateMemoryStreamFromPointer(buffer, (int)buffer.LongLength, out this._Reference) : CanonSDK.EdsCreateMemoryStreamFromPointer(buffer, buffer.LongLength, out this._Reference);
			ErrorHandler.CheckError(errorCode);
		}

		public SDKStream(IntPtr buffer, long length)
		{
			if (buffer == IntPtr.Zero)
			{
				throw new ArgumentNullException("buffer");
			}
			ErrorCode errorCode = (!CanonSDK.IsVerGE34) ? CanonSDK.EdsCreateMemoryStreamFromPointer(buffer, (int)length, out this._Reference) : CanonSDK.EdsCreateMemoryStreamFromPointer(buffer, length, out this._Reference);
			ErrorHandler.CheckError(errorCode);
		}

		[Obsolete("Not necessary anymore. Buffer and length is not used.")]
		public SDKStream(IntPtr buffer, IntPtr sdkStream, long length)
			: this(sdkStream)
		{
		}

		public override void Flush()
		{
		}

		public override int Read(byte[] buffer, int offset, int count)
		{
			return (int)this.Read(buffer, offset, count);
		}

		public unsafe long Read(byte[] buffer, long offset, long count)
		{
			if (buffer.LongLength < offset + count)
			{
				throw new ArgumentOutOfRangeException();
			}
			fixed (byte* ptr = buffer)
			{
				byte* value = ptr + offset;
				if (CanonSDK.IsVerGE34)
				{
					long result = default(long);
					ErrorHandler.CheckError(CanonSDK.EdsRead(this._Reference, count, (IntPtr)(void*)value, out result));
					return result;
				}
				int num = default(int);
				ErrorHandler.CheckError(CanonSDK.EdsRead(this._Reference, (int)count, (IntPtr)(void*)value, out num));
				return num;
			}
		}

		public override long Seek(long offset, System.IO.SeekOrigin origin)
		{
			EOSDigital.SDK.SeekOrigin inSeekOrigin;
			switch (origin)
			{
			case System.IO.SeekOrigin.Begin:
				inSeekOrigin = EOSDigital.SDK.SeekOrigin.Begin;
				break;
			case System.IO.SeekOrigin.Current:
				inSeekOrigin = EOSDigital.SDK.SeekOrigin.Current;
				break;
			case System.IO.SeekOrigin.End:
				inSeekOrigin = EOSDigital.SDK.SeekOrigin.End;
				break;
			default:
				throw new ArgumentException("Not a valid enum value", "origin");
			}
			if (CanonSDK.IsVerGE34)
			{
				ErrorHandler.CheckError(CanonSDK.EdsSeek(this._Reference, offset, inSeekOrigin));
			}
			else
			{
				ErrorHandler.CheckError(CanonSDK.EdsSeek(this._Reference, (int)offset, inSeekOrigin));
			}
			return this.Position;
		}

		public override void SetLength(long value)
		{
			throw new NotSupportedException();
		}

		public override void Write(byte[] buffer, int offset, int count)
		{
			this.Write(buffer, offset, count);
		}

		public unsafe void Write(byte[] buffer, long offset, long count)
		{
			if (buffer.LongLength < offset + count)
			{
				throw new ArgumentOutOfRangeException();
			}
			fixed (byte* ptr = buffer)
			{
				byte* value = ptr + offset;
				if (CanonSDK.IsVerGE34)
				{
					long num = default(long);
					ErrorHandler.CheckError(CanonSDK.EdsWrite(this._Reference, count, (IntPtr)(void*)value, out num));
				}
				else
				{
					int num2 = default(int);
					ErrorHandler.CheckError(CanonSDK.EdsWrite(this._Reference, (int)count, (IntPtr)(void*)value, out num2));
				}
			}
		}

		protected override void Dispose(bool disposing)
		{
			base.Dispose(disposing);
			if (this._Reference != IntPtr.Zero)
			{
				int countOrError = CanonSDK.EdsRelease(this._Reference);
				this.Reference = IntPtr.Zero;
				if (disposing)
				{
					ErrorHandler.CheckError(countOrError);
				}
			}
		}
	}
}
